/**
 * @Author       : Mo 2427995270@qq.com
 * @Date         : 2025-05-29 16:47:08
 * @LastEditTime : 2025-08-03 21:23:32
 * @FilePath     : \ZN-1000-APP\hal_driver\ll_adc.c
 * @Description  : adc低层驱动
 * @Version      : V1.0
 * @History      : 
 * @Note         : 仅支持软件触发
 */
/***************************************Includes***********************************/
#include "ll_adc.h"
#include "ll_gpio.h"
#include "hal_delay.h"

#if defined(GD32F407)
#include "gd32f4xx.h"
#elif defined(STM32F40_41xxx)
#include "stm32f4xx.h"
#elif defined(GD32F10X_HD)
#include "gd32f10x.h"
#elif defined(STM32F10X_HD)
#include "stm32f10x.h"
#elif defined(PY32F071xB)
#include "py32f0xx.h"
#else
#error "No device selected"
#endif

/************************************Private Macros********************************/
//#define


/**********************************Private Statement*******************************/


/***********************************Public Variables*******************************/



/**********************************Private Variables*******************************/



/**********************************Public Functions********************************/

/**
 * @brief adc初始化
 * @param  alt              
 * @param  port             GPIO端口
 * @param  pin              GPIO PIN
 * @param  adcx             ADCx
 * @param  channel          ADC通道
 * @return int 0成功 -1失败
 * @note null
 */
int adc_ll_init(adc_ll_t *alt, uint32_t port, uint32_t pin, uint32_t adcx, uint32_t channel) {
// clang-format off
#if defined(GD32F407) || defined(GD32F10X_HD)
    alt->port = port;
    alt->pin = pin;
    alt->adcx = adcx;
    alt->channel = channel;
    gpio_ll_t gpio_cfg;
    gpio_ll_init(&gpio_cfg, port, pin, GPIO_LL_MODE_ANALOG, GPIO_LL_OTYPE_OD, GPIO_LL_PULL_NO, GPIO_LL_SPEED_MEDIUM, 0);
    
    switch (alt->adcx) {
    case (uint32_t) ADC0: rcu_periph_clock_enable(RCU_ADC0); break;
    case (uint32_t) ADC1: rcu_periph_clock_enable(RCU_ADC1); break;
    case (uint32_t) ADC2: rcu_periph_clock_enable(RCU_ADC2); break;
    default: return -1;
    }
    adc_clock_config(ADC_ADCCK_PCLK2_DIV8);
    // 同步模式: 所有ADC独立工作
    adc_sync_mode_config(ADC_SYNC_MODE_INDEPENDENT);
    // 连续采样关闭
    adc_special_function_config(alt->adcx, ADC_CONTINUOUS_MODE, DISABLE);
    // 扫描模式禁用
    adc_special_function_config(alt->adcx, ADC_SCAN_MODE, DISABLE);
    // 数据对齐
    adc_data_alignment_config(alt->adcx, ADC_DATAALIGN_RIGHT);
    // 通道长度1
    adc_channel_length_config(alt->adcx, ADC_ROUTINE_CHANNEL, 1);
    // 外部触发禁用
    adc_external_trigger_config(alt->adcx, ADC_ROUTINE_CHANNEL, EXTERNAL_TRIGGER_DISABLE);
    adc_enable(alt->adcx);
    delay_ms_not_os(1);
    adc_calibration_enable(alt->adcx);
    return 0;
#elif defined(STM32F40_41xxx) || defined(STM32F10X_HD)
    #error "adc驱动未实现"
#elif defined(PY32F071xB)
    alt->port = port;
    alt->pin = pin;
    alt->adcx = adcx;
    alt->channel = channel;
    gpio_ll_t gpio_cfg;
    gpio_ll_init(&gpio_cfg, port, pin, GPIO_LL_MODE_ANALOG, GPIO_LL_OTYPE_OD, GPIO_LL_PULL_NO, GPIO_LL_SPEED_MEDIUM, 0);
    __HAL_RCC_ADC_CLK_ENABLE();
    RCC_PeriphCLKInitTypeDef rcc_init = {0};
    rcc_init.PeriphClockSelection = RCC_PERIPHCLK_ADC;
    rcc_init.ADCClockSelection = RCC_ADCCLKSOURCE_PCLK_DIV4;
    HAL_RCCEx_PeriphCLKConfig(&rcc_init);
    ADC_HandleTypeDef *handle = (void *)adcx;
    handle->Init.Resolution = ADC_RESOLUTION_12B;
    handle->Init.DataAlign = ADC_DATAALIGN_RIGHT;
    handle->Init.ScanConvMode = ADC_SCAN_DISABLE;
    handle->Init.ContinuousConvMode = DISABLE;
    handle->Init.NbrOfConversion = 1;
    handle->Init.DiscontinuousConvMode = DISABLE;
    handle->Init.NbrOfDiscConversion = 1;
    handle->Init.ExternalTrigConv = ADC_SOFTWARE_START;
    HAL_ADC_Init(handle);
    HAL_ADC_ConfigVrefBuf(handle, ADC_VREFBUF_2P5V);
    HAL_ADCEx_Calibration_Start(handle);
#endif
// clang-format on
    return -1;
}
/**
 * @brief 所有ADC复位
 * @note null
 */
void adc_ll_deinit(adc_ll_t *alt) {
#if defined(GD32F407) || defined(GD32F10X_HD)
    adc_deinit();
#elif defined(STM32F40_41xxx) || defined(STM32F10X_HD)

#elif defined(PY32F071xB)
    HAL_ADC_DeInit((void *)(alt->adcx));
#endif
}

/**
 * @brief ADC采样
 * @param  alt              
 * @return uint16_t 采样值
 * @note null
 */
uint16_t adc_ll_sample(adc_ll_t *alt) {
#if defined(GD32F407) || defined(GD32F10X_HD)
    // 配置通道
    adc_routine_channel_config(alt->adcx, 0, alt->channel, ADC_SAMPLETIME_56);
    // 软件触发使能
    adc_software_trigger_enable(alt->adcx, ADC_ROUTINE_CHANNEL);
    while (!adc_flag_get(alt->adcx, ADC_FLAG_EOC)) {
        ;
    }
    adc_flag_clear(alt->adcx, ADC_FLAG_EOC);
    return adc_routine_data_read(alt->adcx);
#elif defined(STM32F40_41xxx) || defined(STM32F10X_HD)
    #error "adc驱动未实现"
#elif defined(PY32F071xB)
    ADC_ChannelConfTypeDef channel_cfg;
    channel_cfg.Channel = alt->channel;
    channel_cfg.Rank = ADC_REGULAR_RANK_1;
    channel_cfg.SamplingTime = ADC_SAMPLETIME_134CYCLES_5;
    HAL_ADC_ConfigChannel((void *)(alt->adcx), &channel_cfg);
    HAL_ADC_Start((void *)(alt->adcx));
    while (!__HAL_ADC_GET_FLAG(((ADC_HandleTypeDef *)alt->adcx), ADC_FLAG_EOC)) {
        
    }
    __HAL_ADC_CLEAR_FLAG(((ADC_HandleTypeDef *)alt->adcx), ADC_FLAG_EOC);
    return HAL_ADC_GetValue((void *)alt->adcx);
#endif
    return 0;
}


/**********************************Private Functions*******************************/


/* [] END OF FILE */
